package crm8000.services

import crm8000.Models.Customer;
import crm8000.Models.Goods;
import crm8000.Models.Invertory;
import crm8000.Models.InvertoryDetail
import crm8000.Models.Receivables;
import crm8000.Models.ReceivablesDetail;
import crm8000.Models.User;
import crm8000.Models.WSBill;
import crm8000.Models.WSBillDetail;
import crm8000.Models.Warehouse;
import crm8000.helper.Result
import crm8000.viewModels.WsBillVM
import grails.transaction.Transactional

/**
 * 销售出库单Service
 *
 */
@Transactional
class WsBillService {
	UserService userService

	def wsbillList() {
		def data = WSBill.findAllByBillStatus(0);
		def result = []

		for (item in data) {
			def pw = new WsBillVM(id: item.id, ref: item.ref,
			bizDate: item.bizDT.format("yyyy-MM-dd"),
			customerName: item.customer.name,
			warehouseName: item.warehouse.name,
			billStatus: "待提交",
			inputUserName: item.inputUser.name,
			bizUserName: item.bizUser.name)

			pw.amount = WSBillDetail.createCriteria().get {
				projections { sum("goodsMoney") }
				wsBill { eq "id", item.id }
			}

			result.add(pw)
		}
		return result
	}

	def wsBillInfo(String id) {
		return WSBill.get(id)
	}

	Result editWSBill(params) {
		if (params.id) {
			// 编辑
			def user = User.get(params.bizUserId)
			if (!user) {
				return new Result(success: false, msg: "业务人员不存在")
			}
			def warehouse = Warehouse.get(params.warehouseId)
			if (!warehouse) {
				return new Result(success: false, msg: "仓库不存在")
			}
			def customer = Customer.get(params.customerId)
			if (!customer) {
				return new Result(success: false, msg: "供应商不存在")
			}

			def bill = WSBill.get(params.id)
			if (!bill) {
				return new Result(success: false, msg: "销售出库单不存在")
			}

			if (bill.billStatus != 0) {
				return new Result(success: false, msg: "当前销售出库单已经提交，不能再编辑")
			}

			bill.customer = customer
			bill.warehouse = warehouse
			bill.bizUser = user
			bill.inputUser = userService.loginUser
			bill.bizDT = Date.parse("yyyy-MM-dd", params.bizDT)
			bill.save()

			return new Result(success: true, id: bill.id)
		} else {
			// 新增
			def user = User.get(params.bizUserId)
			if (!user) {
				return new Result(success: false, msg: "业务人员不存在")
			}
			def warehouse = Warehouse.get(params.warehouseId)
			if (!warehouse) {
				return new Result(success: false, msg: "仓库不存在")
			}
			def customer = Customer.get(params.customerId)
			if (!customer) {
				return new Result(success: false, msg: "供应商不存在")
			}

			def bill = new WSBill()
			bill.ref = this.genNewBillRef();
			bill.customer = customer
			bill.warehouse = warehouse
			bill.bizUser = user
			bill.inputUser = userService.loginUser
			bill.bizDT = Date.parse("yyyy-MM-dd", params.bizDT)
			bill.billStatus = 0
			bill.save()

			return new Result(success: true, id: bill.id)
		}
	}

	Result deleteWSBill(String id) {
		def bill = WSBill.get(id)
		if (!bill) {
			return new Result(success: false, msg: "要删除的销售出库单不存在")
		}

		if (bill.billStatus != 0) {
			return new Result(success: false, msg: "当前销售出库单已经提交，不能删除")
		}

		bill.delete()

		return new Result(success: true)
	}

	def wsBillDetailList(String billId) {
		return WSBillDetail.createCriteria().list {
			wsBill { eq "id", billId }
			order "showOrder"
		}
	}

	/**
	 * 生成销售出库单的新单号
	 * @return 新单号
	 */
	private String genNewBillRef() {
		def pre = "WS"
		def mid = new Date().format("yyyyMMdd")
		def bill = WSBill.createCriteria().get {
			ilike "ref", pre + mid + "%"
			order "ref", "desc"
			maxResults 1
		}
		if (!bill) {
			return pre + mid + "001"
		} else {
			def suf = (bill.ref.substring(10).toInteger() + 1).toString()
			def str = ""
			for (int i = 0; i < 3 - suf.length(); i++) {
				str += "0"
			}
			suf = str + suf

			return pre + mid + suf
		}
	}

	Result editWSBillDetail(params) {
		def bill = WSBill.get(params.billId)
		if (!bill) {
			return new Result(success: false, msg: "销售出库单主记录不存在")
		}

		if (bill.billStatus != 0) {
			return new Result(success: false, msg: "销售出库单已经提交，不能再新建商品明细记录")
		}

		def goods = Goods.get(params.goodsId)
		if (!goods) {
			return new Result(success: false, msg: "商品不存在")
		}

		def goodsPrice = params.goodsPrice.toBigDecimal()
		def goodsCount = params.goodsCount.toInteger()
		def goodsMoney = goodsCount * goodsPrice

		if (params.id) {
			// 编辑
			def detail = WSBillDetail.get(params.id)
			if (!detail) {
				return new Result(success: false, msg: "要编辑的商品明细记录不存在")
			}
			detail.goods = goods
			detail.goodsPrice = goodsPrice
			detail.goodsCount = goodsCount
			detail.goodsMoney = goodsMoney

			detail.save()

			return new Result(success: true, id: detail.id)
		} else {
			// 新建
			def detail = new WSBillDetail()
			detail.wsBill = bill
			detail.goods = goods
			detail.goodsPrice = goodsPrice
			detail.goodsCount = goodsCount
			detail.goodsMoney = goodsMoney
			def showOrder = WSBillDetail.createCriteria().get {
				projections { max("showOrder") }
				wsBill { eq "id", bill.id }
			}
			if (!showOrder) {
				showOrder = 0
			}
			detail.showOrder = showOrder + 1
			detail.save()

			return new Result(success: true, id: detail.id)
		}
	}

	def refreshWSBillInfo(String id) {
		return WSBillDetail.createCriteria().get {
			projections { sum("goodsMoney") }
			wsBill { eq "id", id }
		}
	}

	def wsBillDetailInfo(id) {
		return WSBillDetail.get(id)
	}

	Result deleteWSBillDetail(String id) {
		def detail = WSBillDetail.get(id)
		if (!detail) {
			return new Result(success: false, msg: "要删除的商品明细记录不存在")
		}

		if (detail.wsBill.billStatus != 0) {
			return new Result(success: false, msg: "当前销售出库单已经提交，不能再删除商品明细记录")
		}

		detail.delete()

		return new Result(success: true)
	}

	/**
	 * 提交销售出库单
	 * @param id
	 * @return
	 */
	Result commitWSBill(String id) {
		def bill = WSBill.get(id)
		if (!bill) {
			return new Result(success: false, msg: "要提交的销售出库单不存在")
		}

		if (bill.billStatus != 0) {
			return new Result(success: false, msg: "当前销售出库单已经提交过，不能再次提交")
		}

		if (!bill.warehouse.inited) {
			return new Result(success: false, msg: "仓库 [<span style='color:red'>${bill.warehouse.name}</span>] 还没有完成建账，不能对其做出库操作")
		}

		if (bill.details.size() == 0) {
			return new Result(success: false, msg: "当前销售出库单没有录入商品明细，不能提交")
		}

		// 检查出库数量,出库数量必须为正数
		for (detail in bill.details) {
			if (detail.goodsCount <= 0) {
				return new Result(success: false, msg: "商品 [${detail.goods.name}] 的销售数量必须大于0")
			}
		}
		
		def result = new Result(success: false)

		WSBill.withTransaction { status ->
			for (detail in bill.details) {
				def g = detail.goods
				// 记录总账
				def inv = Invertory.findByGoodsAndWarehouse(g, bill.warehouse)
				if (inv == null) {
					status.setRollbackOnly()
					result.msg = "仓库 [${bill.warehouse.name}] 里没有商品 [${g.name}]，无法出库"
					return
				}

				if (inv.balanceCount < detail.goodsCount) {
					status.setRollbackOnly()
					result.msg = "商品${g.name}库存不足，无法出库"
					return
				}

				if (inv.outCount == null) {
					inv.outCount = 0
				}
				if (inv.outMoney == null) {
					inv.outMoney = 0
				}

				detail.invertoryMoney = inv.balancePrice * detail.goodsCount

				inv.outCount += detail.goodsCount
				inv.outMoney += inv.balancePrice * detail.goodsCount
				inv.outPrice = inv.outMoney / inv.outCount
				inv.balanceCount -= detail.goodsCount
				if (inv.balanceCount > 0) {
					inv.balanceMoney -= inv.balancePrice * detail.goodsCount
					inv.balancePrice = inv.balanceMoney / inv.balanceCount
				} else {
					// 当库存数量为0的时候，把金额全部转出
					detail.invertoryMoney = inv.balanceMoney
					
					inv.balancePrice = 0
					inv.balanceMoney = 0
				}
				inv.save()

				detail.invertoryPrice = detail.invertoryMoney / detail.goodsCount
				detail.save()

								// 记录明细账
				def invDetail = new InvertoryDetail()
				invDetail.warehouse = bill.warehouse
				invDetail.goods = g
				invDetail.outCount = detail.goodsCount
				invDetail.outPrice = detail.invertoryPrice
				invDetail.outMoney = detail.invertoryMoney
				invDetail.balanceCount = inv.balanceCount
				invDetail.balancePrice = inv.balancePrice
				invDetail.balanceMoney = inv.balanceMoney

				invDetail.refNumber = bill.ref
				invDetail.refType = "销售出库"

				invDetail.bizDate = bill.bizDT
				invDetail.bizUser = bill.bizUser

				invDetail.save()
			}

			bill.saleMoney = WSBillDetail.createCriteria().get {
				projections { sum("goodsMoney") }
				wsBill { eq "id", bill.id }
			}
			bill.invertoryMoney = WSBillDetail.createCriteria().get {
				projections { sum("invertoryMoney") }
				wsBill { eq "id", bill.id }
			}
			bill.profit = bill.saleMoney - bill.invertoryMoney
			
			bill.billStatus = 1
			bill.save()

			// 记应收账款，按客户汇总
			def rec = Receivables.findByCaIdAndCaType(bill.customer.id, "customer")
			if (!rec) {
				rec = new Receivables(caId: bill.customer.id, caType: "customer", 
					rvMoney: bill.saleMoney, actMoney: 0, balanceMoney: bill.saleMoney)
				rec.save()
			} else {
				rec.rvMoney += bill.saleMoney
				rec.balanceMoney += bill.saleMoney
				
				rec.save()
			}
			
			// 记应收账款，按单据汇总
			def recDetail = new ReceivablesDetail()
			recDetail.refType = "销售出库"
			recDetail.refNumber = bill.ref
			recDetail.caId = bill.customer.id
			recDetail.caType = "customer"
			recDetail.actMoney = 0
			recDetail.rvMoney = bill.saleMoney
			recDetail.balanceMoney = bill.saleMoney
			
			recDetail.save()
			
			result.success = true
		}

		return result
	}
}
